#ifndef CONFIG_H
#define CONFIG_H

#include <eq/eq.h>
#include <eq/admin/base.h>

// members
#include "localInitData.h"
#include "frameData.h"
#include "tracker.h"
#include "body.h"
//#include "cameraAnimation.h"


namespace eqPc
{
    class View;

    /**
     * The configuration, run be the EqPly application. 
     *
     * A configuration instance manages configuration-specific data: it
     * distributes the initialization and model data, updates frame-specific
     * data and manages frame generation based on event handling. 
     */
    class Config : public eq::Config
    {
    public:

        Config( eq::ServerPtr parent );

        /** @sa eq::Config::init. */
        virtual bool init();
        /** @sa eq::Config::exit. */
        virtual bool exit();

        /** @sa eq::Config::startFrame. */
        virtual uint32_t startFrame();

        void setInitData( const LocalInitData& data ) { _initData = data; }
        const InitData& getInitData() const { return _initData; }

        /** Map per-config data to the local node process */
        bool mapData( const eq::uint128_t& initDataID );

        /** Unmap per-config data to the local node process */
        void unmapData();

        /** @return the requested, default model or 0. */
        const pc::PointCloud* getModel( const eq::uint128_t& id );

        /** @sa eq::Config::handleEvent */
        virtual bool handleEvent( const eq::ConfigEvent* event );

        /** @return true if the application is idling. */
        bool isIdleAA();

        /** @return true if an event required a redraw. */
        bool needRedraw();

        /** @return the current animation frame number. */
        //uint32_t getAnimationFrame();

    protected:
        virtual ~Config();

        /** Synchronize config and admin copy. */
        virtual co::uint128_t sync( 
                             const co::uint128_t& version = co::VERSION_HEAD );

    private:
        int         _spinX, _spinY;
        int         _advance;
        eq::Canvas* _currentCanvas;

        LocalInitData _initData;
        FrameData     _frameData;

        Tracker _tracker;

		PointClouds _pointClouds;
		PointCloudDists _pointCloudDists;
        co::base::Lock  _modelLock;


        uint64_t _messageTime;

        bool _redraw;
        bool _useIdleAA;

        int32_t _numFramesAA;

        eq::admin::ServerPtr _admin;


        void _loadModels();
        void _registerModels();
        void _loadPath();
        void _deregisterData();

        bool _needNewFrame();
        bool _handleKeyEvent( const eq::KeyEvent& event );

        void _switchCanvas();
        void _switchView();
        void _switchViewMode();
        void _switchModel();
        void _freezeLoadBalancing( const bool onOff );
        void _adjustTileSize( const int delta );
        void _switchLayout( int32_t increment );
        void _toggleEqualizer();

        void _setHeadMatrix( const eq::Matrix4f& matrix );
        const eq::Matrix4f& _getHeadMatrix() const;
        void _changeFocusDistance( const float delta );
        void _setFocusMode( const eq::FocusMode mode );

        /** @return a pointer to a connected admin server. */
        //eq::admin::ServerPtr _getAdminServer();
        //void _closeAdminServer();

        View* _getCurrentView();
        const View* _getCurrentView() const;

        void _setMessage( const std::string& message );
        void _updateData();
    };
}

#endif // EQ_PLY_CONFIG_H
